#!/usr/bin/env python

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; specifically version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: Red Hat Inc. 2014
# Author: Cleber Rosa <cleber@redhat.com>

"""
Avocado Journal Replay Utility. Sends test journal data to an Avocado Server.
"""

import sys
import sqlite3
import argparse

import requests


class ArgumentParser(argparse.ArgumentParser):

    def __init__(self):
        super(ArgumentParser, self).__init__(
            prog='avocado-journal-replay',
            description=('Avocado Test Journal Replay. Sends test journal data '
                         'to an Avocado Server'))

        self.add_argument('-s', '--server-uri',
                          help=('Avocado server http URI. Example: '
                                'http://avocado-server:8000'))
        self.add_argument('-u', '--username',
                          help='Username to authenticate to Avocado Server')
        self.add_argument('-p', '--password',
                          help='Password to authenticate to Avocado Server')
        self.add_argument('-n', '--job-name',
                          help='Name to give to job on the Avocado Server')
        self.add_argument('-j', '--journal-path',
                          help='Path to the journal file (.journal.sqlite)')


class App(object):

    def __init__(self):
        self.app_parser = ArgumentParser()
        self.args = None

    def replay_test_activity(self, job, tag, time, action, status):
        action_uri = 'jobs/%s/test_activity' % job
        full_uri = "%s/%s/" % (self.args.server_uri, action_uri)

        data = {'activity': action,
                'status': status,
                'job': job,
                'time': time,
                'test_tag': tag}

        r = requests.post(full_uri,
                          auth=(self.args.username,
                                self.args.password),
                          data=data)

        if r.status_code == 200:
            return True
        else:
            return False

    def create_job(self, unique_id):
        action_uri = 'jobs'
        full_uri = "%s/%s/" % (self.args.server_uri, action_uri)

        data = {'name': self.args.job_name,
                'uniqueident': str(unique_id)}

        r = requests.post(full_uri,
                          auth=(self.args.username,
                                self.args.password),
                          data=data)

        if r.status_code == 201:
            return r.json()['id']
        else:
            print("Failed to add job. reason(s): %s" % r.text)
            return False

    def replay(self):
        journal = sqlite3.connect(self.args.journal_path)
        journal_cursor = journal.cursor()
        job_unique_id_sql = 'SELECT unique_id FROM job_info'
        job_unique_id = journal_cursor.execute(job_unique_id_sql).fetchone()[0]

        job_result = self.create_job(job_unique_id)
        if not job_result:
            return -1

        while True:
            journal = sqlite3.connect(self.args.journal_path)
            journal_cursor = journal.cursor()

            backlog_count_sql = "SELECT COUNT(*) FROM test_journal WHERE flushed==0"
            backlog_count = journal_cursor.execute(backlog_count_sql).fetchone()[0]

            journal_cursor.close()
            journal.close()

            if backlog_count == 0:
                break

            entry_sql = ("SELECT tag, time, action, status "
                         "FROM test_journal WHERE flushed==0 "
                         "ORDER BY time LIMIT 1")

            journal = sqlite3.connect(self.args.journal_path)
            journal_cursor = journal.cursor()
            entry = journal_cursor.execute(entry_sql).fetchone()
            journal_cursor.close()
            journal.close()

            tag, time, action, status = entry
            activity_result = self.replay_test_activity(job_result,
                                                        tag,
                                                        time,
                                                        action,
                                                        status)
            if activity_result:
                flush_sql = ("UPDATE test_journal SET flushed=1 WHERE "
                             "tag=='%s' AND action=='%s' AND flushed==0")
                flush_sql = flush_sql % (tag, action)

                journal = sqlite3.connect(self.args.journal_path)
                journal_cursor = journal.cursor()
                flush_result = journal_cursor.execute(flush_sql)
                journal.commit()
                journal_cursor.close()
                journal.close()

    def run(self):
        self.args = self.app_parser.parse_args()
        return self.replay()


if __name__ == '__main__':
    app = App()
    sys.exit(app.run())
